<template>
  <view class="page">
    <!-- 顶部导航 -->
    <view class="nav-bar">
      <view class="left">
        <view class="back-btn" @click="goBack">
          <wd-icon name="arrow-left" size="40rpx" color="#64748b" />
        </view>
        <text class="title">{{ memory ? '编辑' : '新建' }}</text>
      </view>
      <view class="right">
        <view class="clear-btn" @click="showClearConfirm">
          <wd-icon name="delete" size="40rpx" color="#64748b" />
        </view>
        <view class="save-btn" @click="saveMemory">
          <text>保存</text>
        </view>
      </view>
    </view>

    <!-- 编辑区域 -->
    <scroll-view class="editor-scroll" scroll-y>
      <view class="editor-container">
        <!-- 标题输入 -->
        <input
          class="title-input"
          v-model="title"
          placeholder="无标题"
          placeholder-class="placeholder"
        />

        <!-- 内容编辑区 -->
        <view class="content-area">
          <editor
            id="editor"
            class="rich-editor"
            :placeholder="'开始记录...'"
            @ready="onEditorReady"
            @input="onEditorInput"
            :show-img-size="false"
            :show-img-toolbar="false"
            :show-img-resize="false"
          />
        </view>
      </view>
    </scroll-view>

    <!-- 底部工具栏 -->
    <view class="editor-toolbar">
      <view class="toolbar-container">
        <view class="toolbar-list">
          <view
            class="toolbar-item"
            v-for="tool in mediaTools"
            :key="tool.name"
            @click="tool.action"
          >
            <wd-icon :name="tool.icon" size="44rpx" :color="tool.active ? '#3b82f6' : '#64748b'" />
            <text class="toolbar-label">{{ tool.label }}</text>
          </view>
        </view>
      </view>
      <view class="safe-area-inset-bottom"></view>
    </view>

    <!-- 录音弹窗 -->
    <wd-popup v-model="showRecorder" position="bottom" round>
      <view class="recorder-popup">
        <view class="recorder-header">
          <text class="title">{{ isRecording ? '正在录音...' : '按住说话' }}</text>
          <text class="time" v-if="isRecording">{{ formatRecordTime(recordingTime) }}</text>
        </view>
        <view class="recorder-body">
          <view class="wave-animation" :class="{ recording: isRecording }">
            <view class="wave-circle"></view>
            <view class="wave-ripple"></view>
            <view class="mic-icon">
              <wd-icon name="mic" size="40rpx" color="#fff" />
            </view>
          </view>
        </view>
        <view class="recorder-footer">
          <view class="cancel-btn" @click="cancelRecording">取消</view>
          <view
            class="record-btn"
            :class="{ recording: isRecording }"
            @touchstart="startRecording"
            @touchend="stopRecording"
            @touchcancel="cancelRecording"
          >
            <text>{{ isRecording ? '松开结束' : '按住录音' }}</text>
          </view>
        </view>
      </view>
    </wd-popup>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useMemoriesStore } from '@/store/memories'

const memoriesStore = useMemoriesStore()

// 获取回忆 ID 和文件夹 ID
const memoryId = Number(getCurrentPages().pop()?.options?.id || 0)
const folderId = getCurrentPages().pop()?.options?.folderId || 'default'

// 获取文件夹信息
const folder = computed(() =>
  memoriesStore.currentUserData?.folders.find((f) => f.folderId === folderId),
)

// 获取回忆信息
const memory = computed(() => {
  const folder = memoriesStore.currentUserData?.folders.find((f) => f.folderId === folderId)
  return folder?.memorial.find((m) => m.id === memoryId)
})

// 编辑状态
const title = ref('')
const content = ref<string>('')

// 媒体相关状态
const showMenu = ref(false)
const showRecorder = ref(false)
const mediaList = ref<
  Array<{
    type: 'image' | 'video' | 'audio' | 'file'
    url: string
    name?: string
    size?: string
    duration?: string
    fileType?: string
    poster?: string
  }>
>([])

// 录音相关状态
const isRecording = ref(false)
const recordingTime = ref(0)
let recordTimer: ReturnType<typeof setInterval>

// 根据平台初始化录音管理器
const recorderManager = ref()
const h5Recorder = ref<MediaRecorder | null>(null)
const audioChunks = ref<Blob[]>([])

// 文本格式化状态
const isBold = ref(false)
const isItalic = ref(false)

// 定义内容块的类型
interface ContentBlock {
  id: string
  type: 'text' | 'image' | 'video' | 'audio' | 'file'
  content: string // 文本内容或媒体URL
  meta?: {
    name?: string
    size?: string
    duration?: string
    poster?: string
    fileType?: string
  }
}

// 修改数据结构
const blocks = ref<ContentBlock[]>([
  { id: '1', type: 'text', content: '' }, // 初始文本块
])
const currentBlockIndex = ref(0) // 当前光标所在块的索引

const editorCtx = ref<any>(null)

// 初始化数据
onMounted(async () => {
  await memoriesStore.init()

  // 如果有回忆数据，加载到编辑器中
  if (memory.value) {
    title.value = memory.value.title

    // 初始化文本块
    blocks.value = [
      {
        id: '1',
        type: 'text',
        content: memory.value.content,
      },
    ]

    // 添加媒体块
    if (memory.value.mediaList) {
      memory.value.mediaList.forEach((media) => {
        addMedia(media.type, {
          url: media.url,
          ...media,
        })
      })
    }
  }

  initRecorder()
})

// 编辑器初始化完成
const onEditorReady = () => {
  uni
    .createSelectorQuery()
    .select('#editor')
    .context((res) => {
      editorCtx.value = res.context
      // 如果有初始内容，设置到编辑器
      if (memory.value?.content) {
        editorCtx.value.setContents({
          html: memory.value.content,
        })
      }
    })
    .exec()
}

// 编辑器内容变化
const onEditorInput = (e: any) => {
  content.value = e.detail.html
  // 可以在这里处理媒体文件的提取和保存
}

// 插入图片
const chooseImage = async () => {
  try {
    const res = await uni.chooseImage({
      count: 9,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
    })

    // 插入图片到编辑器
    res.tempFilePaths.forEach(async (path) => {
      await editorCtx.value?.insertImage({
        src: path,
        width: '100%',
        success: () => {
          // 保存媒体信息
          mediaList.value.push({
            type: 'image',
            url: path,
          })
        },
      })
    })
  } catch (e) {
    console.error('Choose image failed:', e)
  }
}

// 插入视频
const chooseVideo = async () => {
  try {
    const res = await uni.chooseVideo({
      sourceType: ['album', 'camera'],
      compressed: true,
      maxDuration: 60,
    })

    await editorCtx.value?.insertVideo({
      src: res.tempFilePath,
      poster: res.thumbTempFilePath,
      width: '100%',
      success: () => {
        mediaList.value.push({
          type: 'video',
          url: res.tempFilePath,
          poster: res.thumbTempFilePath,
          duration: formatTime(res.duration),
          size: formatSize(res.size),
        })
      },
    })
  } catch (e) {
    console.error('Choose video failed:', e)
  }
}

// 切换录音弹窗
const toggleRecorder = () => {
  showRecorder.value = !showRecorder.value
}

// 开始录音
const startRecording = async () => {
  // #ifdef H5
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
    h5Recorder.value = new MediaRecorder(stream)
    audioChunks.value = []

    h5Recorder.value.ondataavailable = (e) => {
      audioChunks.value.push(e.data)
    }

    h5Recorder.value.onstop = () => {
      const audioBlob = new Blob(audioChunks.value, { type: 'audio/wav' })
      const audioUrl = URL.createObjectURL(audioBlob)

      // 添加到 blocks
      addMedia('audio', {
        url: audioUrl,
        duration: `${Math.floor(recordingTime.value)}s`,
        size: `${Math.floor(audioBlob.size / 1024)}KB`,
      })

      // 释放媒体流
      stream.getTracks().forEach((track) => track.stop())
      showRecorder.value = false
    }

    h5Recorder.value.start()
    isRecording.value = true
    recordingTime.value = 0

    // 计时器
    recordTimer = setInterval(() => {
      recordingTime.value++
    }, 1000)
  } catch (err) {
    console.error('Failed to start recording:', err)
    uni.showToast({
      title: '无法访问麦克风',
      icon: 'none',
    })
  }
  // #endif

  // #ifdef APP-PLUS || MP-WEIXIN
  if (!recorderManager.value) return

  isRecording.value = true
  recordingTime.value = 0

  // 开始录音
  recorderManager.value.start({
    duration: 600000,
    sampleRate: 44100,
    numberOfChannels: 1,
    encodeBitRate: 192000,
    format: 'mp3',
  })

  // 计时器
  recordTimer = setInterval(() => {
    recordingTime.value++
  }, 1000)
  // #endif
}

// 停止录音
const stopRecording = () => {
  // #ifdef H5
  if (h5Recorder.value && isRecording.value) {
    h5Recorder.value.stop()
    isRecording.value = false
    clearInterval(recordTimer)
  }
  // #endif

  // #ifdef APP-PLUS || MP-WEIXIN
  if (!isRecording.value || !recorderManager.value) return

  isRecording.value = false
  clearInterval(recordTimer)
  recorderManager.value.stop()
  // #endif
}

// 取消录音
const cancelRecording = () => {
  // #ifdef H5
  if (h5Recorder.value) {
    h5Recorder.value.stop()
    isRecording.value = false
    clearInterval(recordTimer)
    audioChunks.value = []
  }
  // #endif

  // #ifdef APP-PLUS || MP-WEIXIN
  if (recorderManager.value) {
    isRecording.value = false
    clearInterval(recordTimer)
    recorderManager.value.stop()
  }
  // #endif

  showRecorder.value = false
}

// 选择文件
const chooseFile = async () => {
  // #ifdef H5
  uni.showToast({
    title: 'H5暂不支持文件上传',
    icon: 'none',
  })

  // #endif
}

// 移除媒体
const removeMedia = async (index: number) => {
  try {
    const res = await uni.showModal({
      title: '确认删除',
      content: '是否删除该媒体文件？',
    })

    if (res.confirm) {
      const media = mediaList.value[index]

      // 删除本地文件
      if (media.url.startsWith('file://') || media.url.startsWith('http')) {
        try {
          await uni.removeSavedFile({
            filePath: media.url,
          })
        } catch (e) {
          console.error('Remove file failed:', e)
        }
      }

      // 如果是音频，停止播放
      if (media.type === 'audio' && isPlaying.value === media.url) {
        audioContext.value?.stop()
        isPlaying.value = ''
      }

      // 从列表中移除
      mediaList.value.splice(index, 1)

      // 更新内存中的数据
      if (memory.value) {
        memory.value.mediaList = mediaList.value

        // 更新文件类型标记
        memory.value.hasAudio = mediaList.value.some((m) => m.type === 'audio')
        memory.value.hasVideo = mediaList.value.some((m) => m.type === 'video')
        memory.value.images = mediaList.value.filter((m) => m.type === 'image').map((m) => m.url)
      }

      // 保存到本地存储
      memoriesStore.save()

      uni.showToast({
        title: '删除成功',
        icon: 'success',
      })
    }
  } catch (e) {
    console.error('Remove media failed:', e)
    uni.showToast({
      title: '删除失败',
      icon: 'error',
    })
  }
}

// 获取文件图标
const getFileIcon = (fileType?: string) => {
  switch (fileType) {
    case 'doc':
    case 'docx':
      return 'word'
    case 'pdf':
      return 'pdf'
    default:
      return 'file'
  }
}

// 保存回忆
const saveMemory = async () => {
  if (!folder.value) return

  // 获取编辑器完整内容
  const html = await new Promise((resolve) => {
    editorCtx.value?.getContents({
      success: (res: any) => resolve(res.html),
    })
  })

  if (memory.value) {
    // 更新已有回忆
    const memoryIndex = folder.value.memorial.findIndex((m) => m.id === memoryId)
    if (memoryIndex === -1) return

    folder.value.memorial[memoryIndex] = {
      ...memory.value,
      title: title.value,
      content: html,
      mediaList: mediaList.value,
      updateTime: new Date().toISOString(),
    }
  } else {
    // 创建新回忆
    const newMemory = {
      id: Date.now(),
      title: title.value,
      content: html,
      mediaList: mediaList.value,
      createTime: new Date().toISOString(),
      updateTime: new Date().toISOString(),
      images: mediaList.value.filter((m) => m.type === 'image').map((m) => m.url),
      hasAudio: mediaList.value.some((m) => m.type === 'audio'),
      hasVideo: mediaList.value.some((m) => m.type === 'video'),
    }

    folder.value.memorial.push(newMemory)
  }

  // 更新文件夹时间
  folder.value.updateTime = new Date().toISOString()

  // 保存到本地存储
  await memoriesStore.save()

  // 修改返回逻辑
  uni.showToast({
    title: '保存成功',
    icon: 'success',
    duration: 1500,
    success: () => {
      setTimeout(() => {
        // 使用 navigateBack 而不是 navigateTo
        uni.navigateBack({
          delta: 1,
        })
      }, 1500)
    },
  })
}

// 返回上一页
const goBack = () => {
  // 检查是否有未保存的更改
  if (
    title.value !== memory.value?.title ||
    content.value !== memory.value?.content ||
    mediaList.value.length > 0
  ) {
    uni.showModal({
      title: '提示',
      content: '有未保存的内容，是否保存？',
      success: async (res) => {
        if (res.confirm) {
          await saveMemory()
        } else {
          // 直接返回上一页
          uni.navigateBack({
            delta: 1,
          })
        }
      },
    })
    return
  }

  // 没有更改，直接返回
  uni.navigateBack({
    delta: 1,
  })
}

// 切换粗体
const toggleBold = () => {
  isBold.value = !isBold.value
  // TODO: 实现文本加粗
}

// 切换斜体
const toggleItalic = () => {
  isItalic.value = !isItalic.value
  // TODO: 实现文本斜体
}

// 切换列表
const toggleList = () => {
  // TODO: 实现列表格式
}

// 切换清单
const toggleChecklist = () => {
  // TODO: 实现清单格式
}

// 清空确认
const showClearConfirm = () => {
  uni.showModal({
    title: '清空内容',
    content: '确定要清空所有内容吗？此操作不可恢复。',
    confirmColor: '#dc2626',
    success: (res) => {
      if (res.confirm) {
        clearContent()
      }
    },
  })
}

// 清空内容
const clearContent = async () => {
  title.value = ''
  // 清空编辑器内容
  editorCtx.value?.clear()
  // 清空媒体列表
  mediaList.value = []
  // 重置内容
  content.value = ''

  // 保存清空后的状态
  if (memory.value && folder.value) {
    const memoryIndex = folder.value.memorial.findIndex((m) => m.id === memoryId)
    if (memoryIndex !== -1) {
      folder.value.memorial[memoryIndex] = {
        ...memory.value,
        title: '',
        content: '',
        mediaList: [],
        updateTime: new Date().toISOString(),
      }
      await memoriesStore.save()
    }
  }

  // 显示提示
  uni.showToast({
    title: '内容已清空',
    icon: 'success',
  })
}

// 音频播放相关
const isPlaying = ref('')
const audioContext = ref<UniApp.InnerAudioContext>()
const audioProgress = ref<Record<string, number>>({})
const currentTime = ref(0)

// 播放音频
const playAudio = (url: string) => {
  if (isPlaying.value === url) {
    audioContext.value?.pause()
    isPlaying.value = ''
    return
  }

  if (audioContext.value) {
    audioContext.value.destroy()
  }

  audioContext.value = uni.createInnerAudioContext()
  audioContext.value.src = url
  audioContext.value.play()
  isPlaying.value = url

  // 监听进度
  audioContext.value.onTimeUpdate(() => {
    if (!audioContext.value) return
    currentTime.value = audioContext.value.currentTime
    audioProgress.value[url] = (audioContext.value.currentTime / audioContext.value.duration) * 100
  })

  // 播放结束
  audioContext.value.onEnded(() => {
    isPlaying.value = ''
    audioProgress.value[url] = 0
    currentTime.value = 0
  })
}

// 格式化时间
const formatTime = (seconds: number) => {
  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = Math.floor(seconds % 60)
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
}

// 图片加载完成
const onImageLoad = (e: any) => {
  // 可以在这里处理图片加载完成后的逻辑
  console.log('Image loaded:', e)
}

// 视频加载完成
const onVideoLoad = (e: any) => {
  // 可以在这里处理视频加载完成后的逻辑
  console.log('Video loaded:', e)
}

const initRecorder = () => {
  // #ifdef H5
  // H5 环境下不需要提前初始化
  // #endif

  // #ifdef APP-PLUS || MP-WEIXIN
  recorderManager.value = uni.getRecorderManager()

  // 监听录音结束
  recorderManager.value.onStop((res) => {
    if (!isRecording.value) return

    // 添加到 blocks
    addMedia('audio', {
      url: res.tempFilePath,
      duration: `${Math.floor(res.duration / 1000)}s`,
      size: `${Math.floor(res.fileSize / 1024)}KB`,
    })

    showRecorder.value = false
  })
  // #endif
}

// 格式化录音时间
const formatRecordTime = (seconds: number) => {
  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = seconds % 60
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
}

// 格式化文件大小
const formatSize = (size: number) => {
  if (size < 1024) {
    return size + 'B'
  } else if (size < 1024 * 1024) {
    return (size / 1024).toFixed(2) + 'KB'
  } else {
    return (size / (1024 * 1024)).toFixed(2) + 'MB'
  }
}

// 添加媒体内容
const addMedia = async (type: 'image' | 'video' | 'audio' | 'file', file: any) => {
  // 在当前光标位置后插入新块
  const newBlock: ContentBlock = {
    id: Date.now().toString(),
    type,
    content: file.url,
    meta: {
      name: file.name,
      size: file.size,
      duration: file.duration,
      poster: file.poster,
      fileType: file.fileType,
    },
  }

  // 在当前块后插入媒体块和新的文本块
  blocks.value.splice(currentBlockIndex.value + 1, 0, newBlock, {
    id: Date.now().toString() + '_text',
    type: 'text',
    content: '',
  })

  // 将光标移动到新文本块
  currentBlockIndex.value += 2
}

// 删除块
const removeBlock = (index: number) => {
  blocks.value.splice(index, 1)
  // 如果删除的是最后一个块，确保至少有一个文本块
  if (blocks.value.length === 0) {
    blocks.value.push({
      id: Date.now().toString(),
      type: 'text',
      content: '',
    })
  }
}

const mediaTools = [
  {
    name: 'image',
    icon: 'image',
    label: '图片',
    action: chooseImage,
    active: false,
  },
  {
    name: 'video',
    icon: 'video',
    label: '视频',
    action: chooseVideo,
    active: false,
  },
  {
    name: 'audio',
    icon: 'mic',
    label: '录音',
    action: toggleRecorder,
    active: false,
  },
  {
    name: 'file',
    icon: 'file',
    label: '文件',
    action: chooseFile,
    active: false,
  },
]

const formatTools = [
  {
    name: 'bold',
    icon: 'bold',
    action: toggleBold,
    active: isBold,
  },
  {
    name: 'italic',
    icon: 'italic',
    action: toggleItalic,
    active: isItalic,
  },
  {
    name: 'list',
    icon: 'list',
    action: toggleList,
    active: false,
  },
  {
    name: 'checklist',
    icon: 'checkbox',
    action: toggleChecklist,
    active: false,
  },
]
</script>

<style lang="scss" scoped>
.page {
  min-height: 100vh;
  padding-bottom: 120rpx; // 为底部工具栏留出空间
  background: #fff;
}

.nav-bar {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20rpx 24rpx;
  background: #fff;
  border-bottom: 1px solid #e2e8f0;

  .left {
    display: flex;
    gap: 16rpx;
    align-items: center;

    .back-btn {
      padding: 8rpx;
    }

    .title {
      font-size: 32rpx;
      font-weight: 500;
      color: #0f172a;
    }
  }

  .right {
    display: flex;
    gap: 16rpx;

    .clear-btn {
      padding: 12rpx;
      color: #64748b;

      &:active {
        opacity: 0.8;
      }
    }

    .save-btn {
      padding: 12rpx 32rpx;
      font-size: 28rpx;
      color: #fff;
      background: #2563eb;
      border-radius: 8rpx;

      &:active {
        opacity: 0.9;
      }
    }
  }
}

.editor-scroll {
  height: calc(100vh - 180rpx); // 减去顶部导航和底部工具栏的高度
  margin-top: 88rpx; // 顶部导航的高度
}

.editor-container {
  padding: 24rpx;

  .title-input {
    width: 100%;
    padding: 16rpx 0;
    margin-bottom: 24rpx;
    font-size: 36rpx;
    font-weight: 500;
    color: #0f172a;
  }

  .content-area {
    flex: 1;
    padding: 24rpx;
    overflow-y: auto;

    .blocks-container {
      display: flex;
      flex-direction: column;
      gap: 8rpx; // 减小块之间的间距
    }

    .content-editor {
      width: 100%;
      min-height: 32rpx; // 减小最小高度
      font-size: 28rpx;
      line-height: 1.6;
      background: transparent;
    }

    .media-block {
      position: relative;
      margin: 4rpx 0; // 更小的外边距
      overflow: hidden;
      background: #f8fafc;
      border-radius: rpx;
    }
  }
}

.placeholder {
  color: #94a3b8;
}

.editor-toolbar {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(10px);
  box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.08);

  .toolbar-container {
    padding: 8rpx 0;
  }

  .toolbar-list {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8rpx;
    padding: 0 24rpx;
  }

  .toolbar-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 16rpx 0;
    border-radius: 12rpx;
    transition: all 0.2s;

    &:active {
      background-color: rgba(0, 0, 0, 0.04);
    }
  }

  .toolbar-label {
    margin-top: 8rpx;
    font-size: 24rpx;
    color: #64748b;
  }

  .safe-area-inset-bottom {
    height: constant(safe-area-inset-bottom);
    height: env(safe-area-inset-bottom);
  }
}

// 录音弹窗样式
.recorder-popup {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 600rpx;
  padding: 48rpx 40rpx 120rpx;
  background: #fff;

  .recorder-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 80rpx;

    .title {
      font-size: 32rpx;
      font-weight: 500;
      color: #1a1a1a;
    }

    .time {
      margin-top: 12rpx;
      font-size: 28rpx;
      color: #2563eb;
    }
  }

  .recorder-body {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: center;

    .wave-animation {
      position: relative;
      width: 240rpx;
      height: 240rpx;

      .wave-circle {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 160rpx;
        height: 160rpx;
        background: rgba(37, 99, 235, 0.1);
        border-radius: 50%;
        transition: all 0.3s;
        transform: translate(-50%, -50%);

        &::before {
          position: absolute;
          width: 100%;
          height: 100%;
          content: '';
          background: inherit;
          border-radius: inherit;
          animation: ripple 2s ease-out infinite;
        }
      }

      .wave-ripple {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 160rpx;
        height: 160rpx;
        background: rgba(37, 99, 235, 0.15);
        border-radius: 50%;
        transition: all 0.3s;
        transform: translate(-50%, -50%);
      }

      .mic-icon {
        position: absolute;
        top: 50%;
        left: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 80rpx;
        height: 80rpx;
        background: #2563eb;
        border-radius: 50%;
        transition: all 0.3s;
        transform: translate(-50%, -50%);

        &.recording {
          transform: translate(-50%, -50%) scale(1.1);
        }
      }

      &.recording {
        .wave-circle,
        .wave-ripple {
          animation: pulse 1.5s ease-in-out infinite;
        }
      }
    }
  }

  .recorder-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 80rpx;

    .cancel-btn {
      padding: 20rpx 40rpx;
      font-size: 28rpx;
      color: #64748b;

      &:active {
        opacity: 0.8;
      }
    }

    .record-btn {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 280rpx;
      height: 88rpx;
      font-size: 28rpx;
      font-weight: 500;
      color: #fff;
      background: #2563eb;
      border-radius: 44rpx;
      transition: all 0.3s;

      &.recording {
        background: #dc2626;
        transform: scale(1.05);
      }

      &:active {
        opacity: 0.9;
        transform: scale(0.98);
      }
    }
  }
}

@keyframes ripple {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(1.8);
  }
}

@keyframes pulse {
  0% {
    transform: translate(-50%, -50%) scale(1);
  }
  50% {
    transform: translate(-50%, -50%) scale(1.1);
  }
  100% {
    transform: translate(-50%, -50%) scale(1);
  }
}

// 音频播放器样式
.audio-player {
  display: flex;
  align-items: center;
  padding: 24rpx;
  margin: 24rpx 0;
  background: #f8fafc;
  border-radius: 12rpx;

  .play-control {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 80rpx;
    height: 80rpx;

    &:active {
      opacity: 0.8;
    }
  }

  .audio-content {
    flex: 1;
    margin: 0 24rpx;

    .audio-wave {
      display: flex;
      gap: 4rpx;
      align-items: center;
      height: 40rpx;
      margin-bottom: 8rpx;

      .wave-line {
        width: 4rpx;
        height: 16rpx;
        background: #cbd5e1;
        border-radius: 2rpx;
        transition: all 0.2s;

        &:nth-child(2n) {
          height: 24rpx;
        }

        &:nth-child(3n) {
          height: 32rpx;
        }

        &.active {
          background: #2563eb;
          animation: waveMove 1s ease-in-out infinite;
        }
      }
    }

    .audio-info {
      display: flex;
      justify-content: space-between;
      font-size: 24rpx;
      color: #64748b;
    }
  }

  .audio-actions {
    padding: 12rpx;

    &:active {
      opacity: 0.8;
    }
  }
}

@keyframes waveMove {
  0%,
  100% {
    height: 16rpx;
  }
  50% {
    height: 32rpx;
  }
}

// 播放控制图标
.play-control {
  [class*='fa-'] {
    font-size: 60rpx;
    color: #2563eb;
  }
}

// 录音图标
.mic-icon {
  [class*='fa-'] {
    font-size: 40rpx;
    color: #fff;
  }
}

// 工具栏图标
.tool-item {
  [class*='fa-'] {
    font-size: 44rpx;
  }
}

.rich-editor {
  width: 100%;
  min-height: 300rpx;
  padding: 24rpx;

  :deep(.ql-container) {
    font-size: 28rpx;
    line-height: 1.6;
  }

  :deep(.audio-player) {
    display: flex;
    align-items: center;
    padding: 24rpx;
    margin: 16rpx 0;
    background: #f8fafc;
    border-radius: 12rpx;
    // ... 音频播放器样式
  }
}
</style>
